/*
 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <math.h>
 #include "ohos_init.h"
 #include "cmsis_os2.h"
 #include "iot_gpio.h"
 #include "hi_io.h"
 #include "iot_errno.h"
 #include "hi_adc.h"
 
 float density, voltage;
 int adcvalue;
 #define COV_RATIO 0.03   
 #define NO_DUST_VOLTAGE 230 
 #define SYS_VOLTAGE 7200 
 
 //递推平均滤波算法
 double Filter(int m)
 {
     static int flag_first = 0, _buff[10], sum;
     const int _buff_max = 10;
     int i;
     if (flag_first == 0)
     {
         flag_first = 1;
         for (i = 0, sum = 0; i < _buff_max; i++)
         {
             _buff[i] = m;
             sum += _buff[i];
         }
     }
     else
     {
         sum -= _buff[0];
         for (i = 0; i < (_buff_max - 1); i++)
         {
             _buff[i] = _buff[i + 1];
         }
         _buff[9] = m;
         sum += _buff[9];
     }
     return  sum/10.0;
 }
 
 /***** 获取电压值函数 *****/
 unsigned int GetVoltage(void)
 {
     unsigned int ret;
     unsigned short data;
     ret = hi_adc_read(HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0xff);//adc读取
     if (ret != IOT_SUCCESS)
         printf("ADC Read Fail\n");//判断是否ADC读取成功
     return data;
 }
 
 double GetGP2Y(void)
 {
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 1);//设置GPIO_7为输出低电平
     usleep(280);
     adcvalue = GetVoltage();
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0);//设置GPIO_7为输出低电平
     adcvalue = Filter(adcvalue);
     voltage = (SYS_VOLTAGE / 4096.0) * adcvalue * 11;
     if(voltage >= NO_DUST_VOLTAGE)
     {
         voltage -= NO_DUST_VOLTAGE;
         density = voltage * COV_RATIO;
     }
     else
         density = 0;
     return density;
  }
 
 static void adc_task(void)
 {
     //初始化GPIO
     IoTGpioInit(HI_IO_NAME_GPIO_0);
     hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_GPIO);//设置GPIO_7的复用功能为普通GPIO
     IoTGpioSetDir(HI_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT);    //设置GPIO_7为输出模式
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0);//设置GPIO_7为输出低电平
     while(1)
     {    
         printf("The current dust concentration is:%4.2fug/m3\n ",GetGP2Y());
         sleep(1);
     }
 }
 
 static void adc_pm2_5(void)
 {
     osThreadAttr_t attr;
     attr.attr_bits = 0U;
     attr.cb_mem = NULL;
     attr.cb_size = 0U;
     attr.stack_mem = NULL;
     attr.stack_size = 1024 * 4;
 
     attr.name = "adc_task";
     attr.priority = 25;
     if(osThreadNew((osThreadFunc_t)adc_task, NULL, &attr) == NULL)
     {
         printf("Falied to create adc_task!\n");
     }
 }
 APP_FEATURE_INIT(adc_pm2_5);